/**
 * File Comment: Nothing to add, 2 audit rules disabled
 */
package edu.gatech.oad.project.operations.data;

import java.io.Serializable;
import java.util.logging.Level;
import java.util.logging.Logger;

import edu.gatech.oad.project.coordinator.Office;
import edu.gatech.oad.project.operations.users.Doctor;
import edu.gatech.oad.project.operations.users.Patient;

/**
 * Java Representation of an appointment. Has a 
 * time, has a doctor, has the treatment records
 * associated with the appointment, and whether
 * the appointment is confirmed or pending.
 * 
 * @author Group 17
 * @version 1.0
 */
public class Appointment implements Serializable{

    /**
     * 
     */
    private static final long serialVersionUID = -5492968956976220908L;

    /**
     * Field record: medical information
     * associated with the current appointment
     */
    private TreatmentRecord record;
    
    /**
     * Field reason: reason for appointment
     */
    private String reason;
    
    /**
     * Field date: the date of the appointment
     */
    private int date;
    
    /**
     * Field time: the time of the appointment
     */
    private int time;
    
    /**
     * Field doc: the desired doctor overseeing the
     * appointment
     */
    private Doctor doc;
    
    /**
     * Field pat: the patient
     */
    private Patient pat;
    
    /**
     * Field status: what stage/state an appointment
     * is in.
     */
    private AppointmentStatus status;
    
    /**
     * Field id: id of the appointment 
     */
    private int id;
    
    /**
     * Field myLogger: holds the logger for the office file
     */
    private static final Logger MYLOGGER = Logger.getLogger("edu.gatech." +
            "oad.project.operations.data");
    
    /**
     * Default constructor for an appointment.
     * Always sets the status to false to represent
     * pending appointments. Only the doctor
     * office personnel may change the appointment's
     * status to confirmed. IF a doctor is physically making the
     * appointment, simply confirm the appointment after 
     * creating it.
     * 
     * @param id the id of the appointment
     * @param date the date
     * @param time the time
     * @param doc the overseeing doctor
     * @param pat the patient involved in the appointment
     * @param reason the reason for the appointment
     */
    public Appointment(int id, int date, int time, Doctor doc,  // $codepro.audit.disable largeNumberOfParameters
            Patient pat, String reason) {
        this.date = date;
        this.time = time;
        this.doc = doc;
        this.pat = pat;
        this.reason = reason;
        this.status = AppointmentStatus.PENDING;
        this.id=id;
        this.record = new TreatmentRecord();
        
        MYLOGGER.addHandler(Office.FILEHANDLER);
        MYLOGGER.setLevel(Level.ALL);
        MYLOGGER.finest("appointment created");
 }
 
    /**
     * Returns the doctor's orders
     * 
     * @return doctors orders
     */
    public DoctorOrders getDocOrders(){
        return this.record.getOrders();
    }
 
    /**
     * sets the doctor's orders
     * 
     * @param newOrders updated information
     */
    public void updateDocOrders(DoctorOrders newOrders){
        MYLOGGER.info("begin update doctor's orders sequence");
        this.record.getOrders().update(newOrders);
    }
 
    /**
     * Adds doctor's orders to the treatment record
     * 
     * @param orders
     */
    public void addDocOrders(DoctorOrders orders) {
        this.record.setOrders(orders);
    }

    /**
     * Adds the actual treatment to the appointment
     * after the appointment is over.
     * 
     * @param r
     */
    public void addRecord(TreatmentRecord r){
        this.record = r;
    }
 
    /**
     * Gives the user the current record
     * 
     * @return the current treatment record
     */
    public TreatmentRecord getRecord() {
        return this.record;
    }
 
    /**
     * Updates the current record by passing in a 
     * temp record with the new information
     * 
     * @param newRecord temp record
     */
    public void updateRecord(TreatmentRecord newRecord){
        MYLOGGER.info("start treatment record update sequence");
        this.record.update(newRecord);
    }
 
    /**
     * Sets the status on the appointment to
     * confirmed.
     */
    public void confirm(){
        MYLOGGER.finest("appointment confirmed");
        this.status = AppointmentStatus.CONFIRMED;
    }
 
    /**
     * Sets the status on the appointment to
     * canceled.
     */
    public void cancel(){
        MYLOGGER.finest("appointment cancelled");
        this.status = AppointmentStatus.CANCELED;
    }
 
    /**
     * Checks to see if the appointment is confirmed
     * 
     * @return true if confirmed, false otherwise
     */
    public boolean isConfirmed(){
        return this.status == AppointmentStatus.CONFIRMED;
    }
 
    /**
     * Checks to see if the appointment is pending
     * 
     * @return true if pending, false otherwise
     */
    public boolean isPending(){
        return this.status == AppointmentStatus.PENDING;
    }
 
    /**
     * Checks to see if the appointment is canceled
     * 
     * @return true if canceled, false otherwise
     */
    public boolean isCanceled(){
        return this.status == AppointmentStatus.CANCELED;
    }
 
    /**
     * @return the date
     */
    public int getDate() {
        return date;
    }
 
    /**
     * @param date the date to set
     */
    public void setDate(int date) {
        this.date = date;
    }
 
    /**
     * @return the time
     */
    public int getTime() {
        return time;
    }

    /**
     * @param time the time to set
     */
    public void setTime(int time) {
        this.time = time;
    }

    /**
     * @return the doc
     */
    public Doctor getDoc() {
        return doc;
    }

    /**
     * @param doc the doc to set
     */
    public void setDoc(Doctor doc) {
        this.doc = doc;
    }
    
    /**
     * @return the patient
     */
    public Patient getPat() {
      return this.pat;
    }
    
    /**
     * @param pat the patient to set
     */
    public void setPat(Patient pat) {
      this.pat = pat;
    }
    
    /**
     * @param reason the reason to set
     */
    public void setReason(String reason) {
        this.reason = reason;
    }

    /**
     * @return the reason
     */
    public String getReason() {
        return reason;
    }
    
    /**
     * @return the id
     */
    public int getID() {
        return this.id;
    }
    
    /**
     * @param id the id to set
     */
    public void setID(int id) {
        this.id = id;
    }

    /**
     * @return the status
     */
    
    public String getStatus() {
        if (this.isPending()) {
            return "pending";
        }
        else if (this.isConfirmed()) {
            return "confirmed";
        }
        else {
            return "cancelled";
        }
    }
    
    /**
     *  Sets the status. Only used when generating appointment
     *  class.
     * @param stat
     */
    public void setStatus(AppointmentStatus stat) {
        this.status = stat;
    }
    
    /**
     * String representation of appointment.
     * Includes all 3 fields.
     * 
     * @return string representation
     */
    @Override
    public String toString() {
        //return "Appointment [date=" + (date/100%100) + "/" + (date%100)
        //        + "/" + (date/10000) + ", time=" + time + ", doc=" + doc 
        //        + ", status=" + status + "]";
        return "Appointment [date=" + Integer.toString(date) + ", time=" 
                + time + ", doc=" + doc + ", status=" + status + "]";
    }
    
    /**
     * Compares date and time
     * 
     * @param app the app to compare
     * @return true if equals, false otherwise
     */
    @Override
    public boolean equals(Object app){    // $codepro.audit.disable
        if (app instanceof Appointment){
            if ((((Appointment) app).getID() == this.id)){
                return true;
            }
        }
        return false;
    }
}
